<?php

/**
 * 小红书JDK
 * @author chenyun
 */
namespace App\Service\VendorClient\ShopXiaohongshuApi;
use App\Service\Code\Normal;
use App\Service\BaseService;
use App\Model\PssLogModel\MicroServiceLog;
use App\Service\HttpServer\Http;
use function GuzzleHttp\json_encode;

class ShopXiaohongshuApiClient extends BaseService
{
    protected $config = [];
    protected $bid    = null;
    private $account  = 'shopxiaohongshu';
    //接口映射
    protected $routeMap = [
        'CategoryGet'        => 'common.getCategories',//获取分类
        'BrandGet'           => 'common.brandSearch',//获取品牌
        'TemplateListGet'    => 'common.getCarriageTemplateList',//获取运费模版
        'AttributeGet'       => 'common.getAttributeLists',//获取属性值
        'MaterialUpload'     => 'material.uploadMaterial', //上传图片素材
        'MaterialDelete'     => 'material.deleteMaterial', //删除图片素材
        'itemAdd'            => 'product.createItemV2',//添加商品
        'getAccessToken'     => 'oauth.getAccessToken',//获取token
        'refreshToken'       => 'oauth.refreshToken',//刷新token
    ];
    public function __construct( $shop = NULL)
    {
        $this->config = @json_decode($shop['extends'], true);
        $this->bid    = $shop['bid'];
        $this->code   = $shop['info'];
    }

    /**
     * 拉取商品分类
     * @param array $param
     */
    public function CategoryGet()
    {
        $requestParam = [
            'method' => 'CategoryGet',
            'data'   => [
                //"categoryId"  =>  "5a310dfa3f7d1712823b9dbe" //查询二级分类
                //"categoryId"  =>  "5a310dfb3f7d1712823b9de1" //查询三级分类
            ],
        ];
        return $this->execute($requestParam);
    }

    /**
     * 拉取商品品牌分类
     * @param array $param
     */
    public function BrandGet()
    {
        $requestParam = [
            'method' => 'BrandGet',
            'data'   => [
                "categoryId"  =>  $this->config["categoryId"]
            ],
        ];
        return $this->execute($requestParam);
    }
    /**
     * 拉取商品属性
     * @param array $param
     */
    public function AttributeGet()
    {
        $requestParam = [
            'method' => 'AttributeGet',
            'data'   => [
                "categoryId"  =>  $this->config["categoryId"]
            ],
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 拉取运费模版
     * @param array $param
     */
    public function TemplateListGet()
    {
        $requestParam = [
            'method' => 'TemplateListGet',
            'data'   => [],
        ];
        return $this->execute($requestParam);
    }
    /**
     * 拉取商品列表
     * @param array $param
     */
    public function productGet(array $param)
    {
        $page     = isset($param['page']) ? $param['page'] : 1 ;
        $pageSize = isset($param['pageSize']) ? $param['pageSize'] : 100 ;
        $requestParam = [
            'method' => 'productGet',
            'data'   => [
                "fields"     => "product_id",
                "page"       => $page,
                "page_size"  => $pageSize,
            ],
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 下架商品
     * @param array $param
     */
    public function productDelistUpdate(string $product_id)
    {
        $requestParam = [
            'method' => 'productDelistUpdate',
            'data'   => [
                "product_id"     => $product_id
            ],
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 上架商品
     * @param array $param
     */
    public function productlistUpdate(array $param)
    {
        $requestParam = [
            'method' => 'productlistUpdate',
            'data'   => [
                "product_id"     => $param['product_id']
            ],
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 更新productQuery基础数据
     * @param array $param
     */
    public function productQuery( array $param)
    {
        $_extra = [
            "fields"    => 'sku_id,spec,pic_list,product_feature',
        ];
        $requestParam = [
            'method' => 'productQuery',
            'data'   => array_merge($param,$_extra),
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 添加商品基础数据
     * @param array $param
     */
    public function itemAdd( array $param)
    {
        $_extra = [
            "brandId"               => (int)$this->config["brandId"],
            "categoryId"            => $this->config["categoryId"],
            "attributes"            => [
                'propertyId' => $this->config["name"],
                'name'       => $this->config["name"],
            ],
        ];
        $requestParam = [
            'method' => 'itemAdd',
            'data'   => array_merge($param,$_extra),
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 更新product基础数据
     * @param array $param
     */
    public function productUpdate( array $param)
    {
        $requestParam = [
            'method' => 'productUpdate',
            'data'   => $param,
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 更新product详情
     * @param array $param
     */
    public function productDetailUpdate( array $param)
    {
        $requestParam = [
            'method' => 'productDetailUpdate',
            'data'   => $param,
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 更新skuUpdate详情
     * @param array $param
     */
    public function skuUpdate( array $param)
    {
        $requestParam = [
            'method' => 'skuUpdate',
            'data'   => $param,
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 推送商品图片上传
     * @param array $param
     * @return mixed
     */
    public function MaterialUpload(array $param) 
    {
        $data=[
            "name"  =>$param["goodsName"],
            "type"  =>"IMAGE",
            "image" =>$param["images"][0],
        ];
        $result_upload = $this->uploadImageSource($data);
        
        if( isset($result_upload['error_code']) && $result_upload['error_code'] !=0) {
            $errorMsg = $result_upload["error_msg"];
            return Normal::returnCode(Normal::FAIL,"处理失败【{$errorMsg}】");
        }
        return Normal::returnCode(Normal::SUC,"处理成功",$result_upload);      
    }

    /**
     * 推送sku图片上传
     * @param array $param
     * @return mixed
     */
    public function skuImageUpload(array $param)
    {
        $sku_id     = $param['sku_id'];
        $image      = $param['image'];
        //获取上传图片的token
        $tokenInfo = $this->getUploadImageSourceToken();
        if($tokenInfo["code"] != Normal::SUC){
            return Normal::returnCode(Normal::FAIL, "没有获取到redirect_url地址");
        }
    
        $redirect_url = $tokenInfo["data"];
        $result_upload = $this->uploadImageSource($redirect_url,$image);
        $pic_url = $result_upload["data"]["src"];
        $requestParam = [
            'method' => 'skuImageUpdate',
            'data'   => [
                'sku_id'    => $sku_id,
                'pic_url'   => $pic_url,
            ],
        ];
        $result = $this->execute($requestParam);
        if( $result["code"] != Normal::SUC ) {
            return Normal::returnCode(Normal::FAIL, "上传sku图片地址失败【{$result['msg']}】",$result);
        }
        return Normal::returnCode(Normal::SUC, "图片上传成功",$result);
    }
    /**
     * 推送商品图片新增
     * @param array $param
     * @return mixed
     */
    public function productImageAdd(array $param) 
    {
        $product_id = $param['product_id'];
        $pic_url    = $param['pic_url'];
        $requestParam = [
            'method' => 'productImageAdd',
            'data'   => [
                'product_id'    => $product_id,
                'pic_url'       => $pic_url,
            ],
        ];
        $result = $this->execute($requestParam);
        if( $result["code"] != Normal::SUC ) {
            return Normal::returnCode(Normal::FAIL, "上次商品图片地址失败【{$result['msg']}】",$result);
        }
        return Normal::returnCode(Normal::SUC, "图片上传成功",$result);
    }
    
    /**
     * 推送商品图片删除
     * @param array $param
     * @return mixed
     */
    public function productImageDelete(array $param) 
    {
        $product_id = $param['product_id'];
        $pic_ids    = $param['pic_ids'];
        $requestParam = [
            'method' => 'productImageDelete',
            'data'   => [
                'product_id'    => $product_id,
                'pic_ids'       => $pic_ids,
            ],
        ];
        $result = $this->execute($requestParam);
        if( $result["code"] != Normal::SUC ) {
            return Normal::returnCode(Normal::FAIL, "productImageDelete失败【{$result['msg']}】",$result);
        }
        return Normal::returnCode(Normal::SUC, "图片删除成功",$result);
    }
    
    /**
     * 上传图片资源
     * @param string $redirect_url
     * @param string $image_path
     * @return mixed
     */
    public function uploadImageSource(array $param)
    {
        $image_path = $param["image"];
        try {
            $filename = date("YmdHis").'_'.rand().'_'.uniqid('Xiaohongshu').'.jpg';
            //读取图片资源
            $image_soure = file_get_contents($image_path);
            //$image_soure=str_split(pack('H*',bin2hex($image_soure)));
            //写入本地指定路径(用完之后删除)
            chmod(__DIR__,777);
            $requestParam = [
                'method' => 'MaterialUpload',
                'data'   => [
                    'name'              => $filename,
                    'type'              => $param["type"],
                    'materialContent'   => base64_encode($image_soure),
                ],
            ];
            $result = $this->execute($requestParam);
            if( $result["code"] != Normal::SUC ) {
                return Normal::returnCode(Normal::FAIL, "上传商品图片地址失败【{$result['msg']}】",$result);
            }
        } catch ( \Exception $th) {
            return Normal::returnCode(Normal::FAIL,"图片上传操作失败【{$th->getMessage()}{$th->getLine()}{$th->getFile()}】");
        }
    }
    
    /**
     * 推送商品sku
     * @param array $sku_add_data
     * @return mixed
     */
    public function skuAdd( array $data = [])
    {
        $_extra = [
            "feature"       => $this->config["sku_feature"],
            "delivery_time" => $this->config["delivery_time"],
            "sku_property"  => $this->config["sku_property"],
        ];
        $requestParam = [
            'method' => 'skuAdd',
            'data'   => array_merge($data,$_extra),
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 推送sku数量
     * @param array $params
     * @return mixed
     */
    public function skuQuantityUpdate(array $param) 
    {
        $data = [
            "sku_id"     => $param['sku_id'],
            "quantity"   => $param['num'],
            "type"       => 1,
        ];
        //组装推送上游数据
        $requestParam = [
            'method' => 'skuQuantityUpdate',
            'data'   => $data,
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 推送sku详情
     * @param array $params
     * @return mixed
     */
    public function skuDetailUpdate(array $param) 
    {
         $data = [
            "sku_id"          => $param['sku_id'],
            "parameter[text]" => $param['description'],
        ];
        //组装推送上游数据
        $requestParam = [
            'method' => 'skuDetailUpdate',
            'data'   => $data,
        ];
        return $this->execute($requestParam);
    }
    
    /**
     * 获取签名
     * @param array $param
     */
    private function getSign($param = [])
    {
        $sign = $param["method"]."?appId=".$param["appId"]."&timestamp=".$param["timestamp"]."&version=".$param["version"].$this->config["AppSecret"];
        return md5($sign);
    }
    
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    private function getAccessToken( $param = [])
    {
        $redis = redis();
        $cache_key = $this->account."_AccessToken";
        $AccessToken = $redis->get($cache_key);
        $token = "";
        $time = time();
        //判断token是否存在
//         if($AccessToken) {
//             $AccessToken           = json_decode($AccessToken,true);
//             $accessTokenExpiresAt  = substr($AccessToken["accessTokenExpiresAt"],0,-3); 
//             $refreshTokenExpiresAt = substr($AccessToken["refreshTokenExpiresAt"],0,-3); 
//             //判断是否accessToken过期
//             if($accessTokenExpiresAt < $time ){
//                 //判断refreshToken是否过期，如果已过期，需要小红书后台重新授权 
//                 if($refreshTokenExpiresAt < $time){
//                     $parameter = [
//                         'method'    => 'refreshToken',
//                         'data'      => [
//                             "refreshToken" => $AccessToken["refreshToken"],
//                         ],
//                     ];
//                     $res =$this->AccessExecute($parameter);
//                 }else{
//                     $parameter = [
//                         'method'    => 'getAccessToken',
//                         'data'      => [],
//                     ];
//                     $res = $this->AccessExecute($parameter);
//                 }
//                 if( $res['code'] != Normal::SUC ) {
//                    return $res;
//                 }
//                 $token = $res["data"]["accessToken"];
//                 $AccessToken = json_encode($res["data"],JSON_UNESCAPED_UNICODE);
//                 $redis->set($cache_key,$AccessToken,60*60*24*7+1500);
//             }else{
//                 $token = $AccessToken["accessToken"];
//             }
//         }else{
            $parameter = [
                'method'    => 'getAccessToken',
                'data'      => [],
            ];
            $res =$this->AccessExecute($parameter);
            if( $res['code'] != Normal::SUC ) {
                return $res;
            }
            $token = $res["data"]["accessToken"];
            $AccessToken = json_encode($res["data"],JSON_UNESCAPED_UNICODE);
            $redis->set($cache_key,$AccessToken,60*60*24*7+1500);
//         }
        return Normal::returnCode(Normal::SUC,"获取成功",$token);
    }
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    private function AccessExecute( $param = [])
    {
        $url    = $this->config["baseurl"];
        $method = $param["method"];
        $param["data"]["appId"]      = $this->config["Appkey"];
        $param["data"]["version"]    = $this->config["version"];
        $param["data"]["timestamp"]  = time();
        $param["data"]["method"]     = $this->routeMap[$method];
        $param["data"]["sign"]       = $this->getSign($param["data"]);
        $param["data"]["code"]       = $this->code;
        $parameter     = [
            "Content-Type:application/json",
        ];
        $result     = Http::apiRequest($url,$param["data"],'post',$parameter,30,false,"json");
        $httpCode   = Http::getHttpCode();
        $response   = @json_decode($result,true);
        $start      = microtime(true);
        $used_time  = bcsub((string)microtime(true), $start,3);
        //写入日志
        MicroServiceLog::instance()->addLog([
            'interface_code'    => $this->account.'_'.$method,
            'request_url'       => $url,
            'request_param'     => json_encode($param["data"],JSON_UNESCAPED_UNICODE),
            'response_code'     => $httpCode,
            'response_data'     => $result,
            'req_used_time'     => $used_time,
        ]);
        if( $response["error_code"] != 0 ) {
            return Normal::returnCode(Normal::FAIL,"code授权失败，请到小红书后台授权！",$response);
        }
        return Normal::returnCode(Normal::SUC,"获取成功",$response["data"]);
    }
    /**
     * CURL请求
     * @param $params
     * @return mixed
     */
    public function execute($param = []) 
    {
        $AccessToken = $this->getAccessToken();
        if($AccessToken["code"] != Normal::SUC){
            return $AccessToken;
        }
        $method                      = $param["method"];
        $url                         = $this->config["baseurl"];
        $param["data"]["method"]     = $this->routeMap[$method];
        $param["data"]["timestamp"]  = time();
        $param["data"]["appId"]      = $this->config["Appkey"];
        $param["data"]["version"]    = $this->config["version"];
        $param["data"]["sign"]       = $this->getSign($param["data"]);
        $param["data"]["accessToken"]= $AccessToken["data"];
        $start                       = microtime(true);
        $response                    = Http::postJsonCurl($url, $param["data"]);
        $used_time                   = bcsub((string)microtime(true), $start,3);
        
        //写入日志
        MicroServiceLog::instance()->addLog([
            'interface_code'    => $this->account.'_'.$method,
            'request_url'       => $url,
            'request_param'     => json_encode($param["data"],JSON_UNESCAPED_UNICODE),
            'response_code'     => 200,
            'response_data'     => $response,
            'req_used_time'     => $used_time,
        ]);
        $result   = @json_decode($response,true);
        if( isset($result['error_code']) && $result['error_code'] !=0) {
            $errorMsg = $result["error_msg"];
            return Normal::returnCode(Normal::FAIL,"处理失败【{$errorMsg}】");
        }
        return Normal::returnCode(Normal::SUC,"处理成功",$result);
    }
}